from flask import abort, jsonify, request
from info.utils.response_code import RET
from . import news_bp
from flask import render_template
from flask import current_app, session
from info import constants, db
from info.models import User, News, Comment, CommentLike
from flask import g
from info.utils.common import login_user_data


@news_bp.route("/<int:news_id>")
@login_user_data
def news_detail(news_id):
    # ----------1. 当用户登录成功后可以使用session 对象获取里面的用户user_id-------------
    # user_id = session.get("user_id")
    # # 2. 根据user_id查询用户对象
    # user = None  # type:User
    # try:
    #
    #     if user_id:
    #         user = User.query.get(user_id)
    # except Exception as e:
    #     current_app.logger.error(e)
    user = g.user

    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg="用户未登录")
    # ----2.查询新闻的点击排行数据-----
    # 1.根据浏览量查询6条点击排行的新闻数据
    try:
        news_model_list = News.query.order_by(News.clicks.desc()).limit(constants.CLICK_RANK_MAX_NEWS)
    except Exception as e:
        current_app.logger.error(e)

    # 3. 将模型列表转成字典列表
    news_dict_list = []
    for news in news_model_list if news_model_list else []:
        # 获取到news对象调用to_dict方法将对象转换成字典,再添加到news_model_list中
        news_dict_list.append(news.to_dict())

    # -----------3.查询新闻的详情数据------------
    try:
        news = News.query.get(news_id)
    except Exception as e:
        current_app.logger.error(e)

    if not news:
        abort(404)
    # 每浏览一次,点击量就加一
    news.clicks += 1

    # 将模型的修改提交到数据库
    try:
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.rollback()
        abort(404)

    # ---------4.查询用户是否收藏过该新闻------------
    is_collected = False
    # false 当前登录用户未关注该新闻的作者
    is_followed = False

    if user:
        if news in user.collection_news:
            # news在用户的收藏的新闻列表内,表示用户收藏过该新闻,is_collected该成True
            is_collected = True
    # 如果用户已经登录且作者存在代表可以关注
    if user and news.user:
        # 当前作者在用户的偶像列表内(已关注)
        if news.user in user.followed:
            is_followed = True

    # -----------5.查询该新闻的评论数据--------------
    try:
        comments = Comment.query.filter(Comment.news_id == news_id).order_by(Comment.create_time.desc()).all()
    except Exception as e:
        current_app.logger.error(e)

    # -------6.需求：查询当前用户在当前新闻的评论里边具体点赞了那几条评论 -------
    # 1. 查询出当前新闻的所有评论，取得所有评论的id —>  list[1,2,3,4,5,6]
    comment_id_list = [comment.id for comment in comments]

    # 2.再通过评论点赞模型(CommentLike)查询当前用户点赞了那几条评论  —>[模型1,模型2...]
    commentlike_model_list = CommentLike.query.filter(CommentLike.comment_id.in_(comment_id_list),
                                                      CommentLike.user_id == user.id
                                                      ).all()

    # 3. comment_like.comment_id通过上一步的模型列表，获取所以点赞过的评论id
    commentlike_id_list = [commentlike.comment_id for commentlike in commentlike_model_list]

    # 模型列表转字典列表
    comment_dict_list = []
    for comment in comments if comments else []:
        comment_dict = comment.to_dict()
        # 评论点赞的标志位
        comment_dict["is_like"] = False
        # 1 2 3 4 5  in  [1,3,5]
        if comment.id in commentlike_id_list:
            comment_dict["is_like"] = True

        comment_dict_list.append(comment_dict)

    data = {
        "user_info": user.to_dict() if user else None,
        "newsClickList": news_model_list,
        "news": news.to_dict(),
        "is_collected": is_collected,
        "is_followed": is_followed,
        "comments": comment_dict_list
    }
    return render_template("news/detail.html", data=data)


@news_bp.route("/news_collect", methods=['POST'])
@login_user_data
def news_collect():
    """收藏和取消收藏接口"""
    """
    1. 获取参数
        1.1 用户对象 新闻id action:(收藏或者取消收藏)
    2. 校验参数
        2.1 非空判断
        2.2 用户是否登录
        2.3 action的值判断
    3. 逻辑实现
        3.1 根据新闻id查询该新闻
        3.2 取消收藏:将新闻对象从news_collection 中取消
        3.3 收藏: 将新闻添加到news_collection中
        3.4 提交修改操作到数据库
    4. 返回值处理
    """
    # 1.1 用户对象 新闻id action:(收藏或者取消收藏)
    params_dict = request.json
    user = g.user
    news_id = params_dict.get("news_id")
    action = params_dict.get("action")

    # 2.1 非空判断
    if not all([user, news_id, action]):
        print(user)
        return jsonify(errno=RET.PARAMERR, errmsg="参数不足")

    # 2.2 用户是否登录
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg="用户不存在")

    # 2.3 action的值判断
    if action not in ["collect", "cancel_collect"]:
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")

    # 3.1 根据新闻id查询该新闻
    news = None
    try:
        news = News.query.get(news_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="查询新闻数据异常")

    if not news:
        return jsonify(errno=RET.NODATA, errmsg="新闻不存在")

    # 收藏
    if action == "collect":
        # 3.2 收藏: 把新闻放到收藏列表
        print(news)
        user.collection_news.append(news)
    else:
        print("haha")
        user.collection_news.remove(news)

    # 3.4 提交修改操作到数据库
    try:
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg="提交数据到数据库异常")
    # 4. 组织响应数据
    return jsonify(errno=RET.OK, errmsg="OK")


@news_bp.route("/news_comment", methods=["POST"])
@login_user_data
def news_comment():
    """评论接口(主评论 子评论)"""
    """
    1. 获取参数
        1.1 用户对象 新闻id 评论内容 parent_id(主评论id)
    2. 校验参数
        2.1 非空判断
        2.2 判断用户是否登录
    3. 逻辑处理
        3.1 根据新闻id查询该新闻(新闻存在才能去评论)
        3.2 创建评论模型 给各个属性赋值
        3.3 判断parent_id是否有值
        3.4 将模型对象保存到数据库
    4. 返回值处理
    """
    # 1.1 用户对象 新闻id 评论内容 parent_id(主评论id)
    params_dict = request.json
    news_id = params_dict.get("news_id")
    comment = params_dict.get("comment")
    parent_id = params_dict.get("parent_id")
    user = g.user

    # 2.1 非空判断
    if not all([news_id, comment]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")

    # 2.2 判断用户是否登录
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg="用户未登录")

    # 3.1 根据新闻id查询该新闻(新闻存在才能去评论)
    try:
        news = News.query.get(news_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.NODATA, errmsg="新闻不存在不能评论")

    # 3.1 创建评论模型 给各个属性赋值
    comment_obj = Comment()
    comment_obj.user_id = user.id
    comment_obj.news_id = news.id
    comment_obj.content = comment

    # 3.3 判断parent_id是否有值
    if parent_id:
        # parent_id有值表示是子评论
        comment_obj.parent_id = parent_id

    # 3.4 将模型对象保存到数据库
    try:
        db.session.add(comment_obj)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg="保存评论对象到数据库异常")

    # 4. 组织响应对象
    return jsonify(errno=RET.OK, errmsg="评论成功", data=comment_obj.to_dict())


@news_bp.route("/comment_like", methods=["POST"])
@login_user_data
def comment_like():
    """评论的点赞,取消点赞"""
    """
    1. 获取参数
        1.1 新闻id 用户 评论id action(add,remove)
    2. 校验参数
        2.1非空判断
        2.2 用户是否登录
        2.3 action是否在["add","remove"]
    3. 逻辑处理
        3.1 根据评论id获取评论模型对象(只有评论存在你才能去点赞)
        3.2 根据action去判断是点赞还是取消点赞
        3.3 点赞 : 根据user_id和comment_id查询CommentLike是否存在
            3.3.1 CommentLike存在表示用户已经点过赞
            3.3.2 CommentLike不存在,添加点赞的状态到CommentLike表中
            3.3.3 点赞后点赞数量要加一
    4. 返回值处理
    """

    # 1.1 新闻id 用户 评论id action(add,remove)
    params_dict = request.json
    news_id = params_dict.get("news_id")
    comment_id = params_dict.get("comment_id")
    action = params_dict.get("action")
    user = g.user

    # 2.1非空判断
    if not all([news_id, comment_id, action]):
        print("1")
        return jsonify(errno=RET.PARAMERR, errmsg="参数不足")

    # 2.2 用户是否登录
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg="用户未登录")

    # 2.3 action是否在["add","remove"]
    if action not in ["add", "remove"]:
        return jsonify(errno=RET.PARAMERR, errmsg="action数据填写错误")

    # 3.1 根据评论id获取评论模型对象(只有评论存在你才能去点赞)
    try:
        comment = Comment.query.get(comment_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="数据库查询错误")

    if not comment:
        return jsonify(errno=RET.NODATA, errmsg="评论不存在")
    # 3.2 根据action去判断是点赞还是取消点赞
    if action == "add":
        # 3.3 点赞 : 根据user_id和comment_id查询CommentLike是否存在
        comment_like = CommentLike.query.filter(CommentLike.user_id == user.id,
                                                CommentLike.comment_id == comment_id).first()
        # 3.3.1 CommentLike存在表示用户已经点过赞
        # 3.3.2 CommentLike不存在,添加点赞的状态到CommentLike表中
        if not comment_like:
            comment_like = CommentLike()
            comment_like.user_id = user.id
            comment_like.comment_id = comment_id
            db.session.add(comment_like)
            # 3.3.3 点赞后点赞数量要加一
            comment.like_count += 1
            print("haha")
    # 取消点赞
    else:
        comment_like = CommentLike.query.filter(CommentLike.user_id == user.id,
                                                CommentLike.comment_id == comment_id).first()
        # CommentLike存在才取消点赞
        if comment_like:
            db.session.delete(comment_like)
            comment.like_count -= 1

    try:
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg="提交数据到数据库异常")

    return jsonify(errno=RET.OK, errmsg="OK")


@news_bp.route("/followed_user", methods=["POST"])
@login_user_data
def followed_user():
    """关注 取消关注"""

    # 1.获取参数
    user_id = request.json.get("user_id")
    user = g.user
    action = request.json.get("action")
    # 2.校验参数
    if not all([user_id, action]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不足")
    # 2.2 用户是否登录
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg="用户未登录")

    if action not in ["follow", "unfollow"]:
        return jsonify(errno=RET.PARAMERR, errmsg="action参数错误")
    # 3.逻辑处理
    try:
        author = User.query.get(user_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="查询作者异常")
    if not author:
        return jsonify(errno=RET.NODATA, errmsg="作者不存在")
    if action == "follow":
        # 关注
        # 作者没有在当前用户的偶像列表
        if author not in user.followed:
            user.followed.append(author)
        else:
            return jsonify(errno=RET.DATAEXIST, errmsg="已经关注该作者")
    else:
        if author in user.followed:
            user.followed.remove(author)

    try:
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="用户保存到数据库失败")

    # 4.返回值处理
    return jsonify(errno=RET.OK, errmsg="操作成功")
